package com.yang.job;

import com.yang.domain.entity.UserBlog;
import com.yang.mapper.BlogMapper;
import com.yang.mapper.UserBlogMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.support.TransactionTemplate;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import static com.yang.constants.RedisConstants.*;

/**
 * <p>
 * 刷新redis的点赞数据到数据库
 * </p>
 * @author yang
 * @date 2023/8/14
 */
@Component
@Slf4j
public class FlushLikeDataJob {

    private static final String PREFIX = BLOG_LIKED_KEY_MAP + "*";
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private BlogMapper blogMapper;
    @Resource
    private UserBlogMapper userBlogMapper;
    @Resource
    private TransactionTemplate transactionTemplate;

    /**
     *
     * 每天上午10点，下午2点，4点
     */
    @Scheduled(cron = "0 0 10,14,16 * * ?")
    public void flushLikeCount2DB() {
        Set<ZSetOperations.TypedTuple<String>> typedTuples = stringRedisTemplate.opsForZSet().rangeWithScores(BLOG_LIKED_CNT, 0, -1);

        if (typedTuples == null || typedTuples.isEmpty()){
            return;
        }

        typedTuples.forEach(tuple -> blogMapper.updateLikeById(tuple.getValue(), tuple.getScore().intValue()));
    }


    /**
     * 每月最后一日的上午10:15触发
     */
    @Scheduled(cron = "0 15 10 L * ?")
    public void flushLikeStatus2DB() {
        Set<String> keys = stringRedisTemplate.keys(PREFIX);

        if (keys == null || keys.isEmpty()){
            return;
        }

        keys.forEach(key -> {
            Map<Object, Object> userLikeMap = stringRedisTemplate.opsForHash().entries(key);
            String[] split = key.split(":");
            String blogId = split[split.length - 1];
            saveOrUpdateUserLikeStatus(blogId,userLikeMap);
        });
    }

    private void saveOrUpdateUserLikeStatus(String blogId, Map<Object, Object> userLikeMap) {

        List<String> allUserIds = userLikeMap.keySet().stream().map(String::valueOf).collect(Collectors.toList());

        List<String> existUserIds = userBlogMapper.findExistUserIds(blogId,allUserIds);

        allUserIds.removeAll(existUserIds);

        // 开启独立线程异步执行
        if (!existUserIds.isEmpty()){
           transactionTemplate.execute((status) -> {
               CompletableFuture.runAsync(() -> updateData(existUserIds,blogId,userLikeMap));
               return Boolean.TRUE;
           });
        }

        if (!allUserIds.isEmpty()){
            transactionTemplate.execute((status) -> {
                insertData(allUserIds,blogId,userLikeMap);
                return Boolean.TRUE;
            });
        }
    }


    /**
     * 修改数据，先删后增
     */
    private void updateData(List<String> existUserIds, String blogId, Map<Object, Object> userLikeMap) {

            userBlogMapper.batchDelete(existUserIds,blogId);

            insertData(existUserIds,blogId,userLikeMap);

    }

    /**
     * 新增数据
     */
    private void insertData(List<String> userIdList, String blogId, Map<Object, Object> userLikeMap) {

        List<UserBlog> userBlogs = userIdList.stream().map(id -> {
            UserBlog userBlog = new UserBlog();
            userBlog.setBlogId(Long.valueOf(blogId));
            userBlog.setUserId(Long.valueOf(id));
            userBlog.setStatus((String) userLikeMap.get(id));
            return userBlog;
        }).collect(Collectors.toList());

        userBlogMapper.insertBatch(userBlogs);

    }


//    /**
//     * 每八小时执行一次
//     */
//   // @Scheduled(cron = "0 0/8 * * * ?")
//    public void flushLikeStatus2DB() {
//        // 找出所有的博客id
//        List<Long> blogIds = blogMapper.selectAllBlogIds();
//
//        // 从redis里面取出数据
//        blogIds.forEach(blogId ->{
//            String key = BLOG_LIKED_KEY_MAP + blogId;
//            Map<Object, Object> userLikeMap = stringRedisTemplate.opsForHash().entries(key);
//            saveOrUpdateUserLikeStatus(blogId,userLikeMap);
//        });
//    }

    //    /**
//     * 新增或者修改数据
//     */
//    private void saveOrUpdateUserLikeStatus(Long blogId, Map<Object, Object> userLikeMap) {
//
//
//        List<Object> userIdList = new ArrayList<>(userLikeMap.keySet());
//        List<String> allUserIds = userIdList.stream().map(String::valueOf).collect(Collectors.toList());
//
//        // 找到存在的用户数据
//        List<String> existUserIds = userBlogMapper.findExistUserIds(blogId,userIdList);
//
//        // 取出掉已经存在的数据
//        userIdList.removeAll(existUserIds);
//
//        if (!existUserIds.isEmpty()){
//            // 开辟一个线程去做另一个操作
//            CompletableFuture.runAsync(() -> updateData(existUserIds,blogId,userLikeMap));
//        }
//
//        if (!allUserIds.isEmpty()){
//            insertData(allUserIds,blogId,userLikeMap);
//        }
//
//    }
}
